#!/usr/bin/env python
# coding:utf-8

"""
Created by ben on 2010/10/26 .
Copyright (c) 2010 http://sa3.org All rights reserved. 
"""

import settings
import logging
import re
import urllib
import fnmatch
import datetime
import time
import math
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.runtime import apiproxy_errors
from google.appengine.ext.webapp import util
from django.utils import simplejson
from util.handler import read_cookies,PublicHandler,get_or_404,FeedHandler
from util.getimageinfo import getImageInfo
from util.paging import PagedQuery
from util.thumb import resize
from models import Album,Image,Comments,Users,getVerificationCode

PAGESIZE = 24 
PAGETIMES = 3
LINKNUM = 7
VERIFICODELEN = 4

def format_date(dt):
    return dt.strftime('%a, %d %b %Y %H:%M:%S GMT')

def get_page_link(tp, cp):
    if LINKNUM >= tp:
        return range(1, tp+1)
    else:
        sti = cp - (LINKNUM-1)/2
        endi = cp + (LINKNUM-1)/2
        if sti > 0:
            if endi > tp:
                sti = sti - (endi - tp)
                if sti < 1:
                    sti = 1
                endi = tp
        else:
            endi = endi - sti + 1
            sti = 1
            if endi > tp:
                endi = tp

        return range(sti, endi+1)

def check_referer(request,referer):
    referer = referer.lower()
    for rule in request.settings.allow_list:
        if fnmatch.fnmatch(referer,rule):
            return True
    logging.info("%s forbidden" % referer)
    return False

class IndexHandler(PublicHandler):
    def get(self):
        p = int(self.request.get('p','1'))
        try:
            if self.settings.theme == 'fcd':
                if self.settings.pic_total_number == 0:
                    tp = Image.get_img_count(None, ['date', '-created'])
                else:
                    tp = int(math.ceil(self.settings.pic_total_number / (PAGESIZE * PAGETIMES)))

                self.template_value['ps']= get_page_link(tp, p)
                self.template_value['Newimg']= Image.get_small_img(None, None, None)
                self.template_value['Hotimg']= Image.get_small_img(['hoted', 'view_count'], None, None)
                self.template_value['Likeimg']= Image.get_small_img(['ilked', 'like_count'], None, None)
                self.template_value['ablumSide']= Album.get_album_list(32)
                self.template_value['prev']=p-1 if p>1 else None
                self.template_value['next'] = p + 1 if (p+1) <= tp else None
                self.template_value['frist']=1 if p>1 else None
                self.template_value['last'] = tp if (p+1) <= tp else None
                self.template_value['current_p'] = p
            else:
                self.template_value['albums']=Album.all()
            self.render('index.html')

        except apiproxy_errors.OverQuotaError, message:
            #Log the error.
            logging.error(message)
            self.template_value['url']='http://p1.vchen.tk/?p=%s' % p
            self.render('relocation.html')
        
class AlbumListHandler(PublicHandler):
    def get(self, key_name):
        p = int(self.request.get('p','1'))
        try:
            album = get_or_404(Album.get_by_key_name,key_name)
            tp = Image.get_img_count(['album', album], ['date', '-created'])
            self.template_value['album_keyname']= album.key().name()
            self.template_value['album_name']= album.name
            self.template_value['ps']= get_page_link(tp, p)
            self.template_value['Newimg']= Image.get_small_img(None, None, None)
            self.template_value['Hotimg']= Image.get_small_img(['hoted', 'view_count'], None, None)
            self.template_value['Likeimg']= Image.get_small_img(['ilked', 'like_count'], None, None)
            self.template_value['ablumSide']= Album.get_album_list(32)
            self.template_value['prev']=p-1 if p>1 else None
            self.template_value['next'] = p + 1 if (p+1) <= tp else None
            self.template_value['frist']=1 if p>1 else None
            self.template_value['last'] = tp if (p+1) <= tp else None
            self.template_value['current_p'] = p
            self.render('album.html')

        except apiproxy_errors.OverQuotaError, message:
            #Log the error.
            logging.error(message)
            self.template_value['url']='http://p1.vchen.tk/b/%s/?p=%s' % (key_name, p)
            self.render('relocation.html')

class ImageListHandler(PublicHandler):
    def get(self,key_name):
        p = int(self.request.get('p','1'))
        i = int(self.request.get('i','1'))
        PAGETIMES = t = int(self.request.get('t','3'))
        if key_name != "_ALL_":
            album = get_or_404(Album.get_by_key_name,key_name)
        showStr = Image.get_img_list(p, i, None if key_name == "_ALL_" else album)
        self.response.headers['Content-Type'] = 'application/json'
        self.response.out.write(showStr)
        
class AddComentsHandler(PublicHandler):
    def post(self):
        name = self.request.get('n')
        email = self.request.get('e')
        comments = self.request.get('c')
        url = self.request.get('u')
        vercode = self.request.get('v')
        img_key = self.request.get('i')

        rs = Comments.add(name, email, url, comments, img_key, vercode)
        self.response.headers['Content-Type'] = 'application/json'
        self.response.out.write(rs)

        
class ImageViewHandler(PublicHandler):
    '''Handler show Image'''
    def get(self,size,key_name):
        referer = self.request.headers.get("Referer")
        if  self.settings.is_anti_leech and referer is not None and (not check_referer(self,referer)):
            #将图片替换为禁止盗链的图片
            key_name = self.settings.anti_leech_img
        #handler If-None-Match
        if size =='s':
            w,h = 120,120
        else:
            w = int(self.request.get("w","0"))
            h = int(self.request.get("h","0"))
        
        key="%s:%s:%s" % (w,h,key_name)
        if_none_match = self.request.headers.get("If-None-Match")
        if if_none_match and if_none_match ==key:
            return self.error(304)
        img = get_or_404(Image.get_by_key_name_with_cache,key_name)
        img.view_count+=1
        img.put()
        mime = str(img.mime) if w ==0 and h==0 else "image/jpeg"
        bf = img.get_resize_img(w,h)
        logging.info(len(bf))
        self.response.headers['Content-Type'] = mime
        self.response.headers['ETag']=key
        self.response.headers['Cache-Control']="max-age=315360000"
        self.response.headers['Last-Modified']=format_date(img.created)
        self.response.out.write(bf)
        
class ImageResizeTestHandler(PublicHandler):
    def get(self,key_name):
        img = get_or_404(Image.get_by_key_name_with_cache,key_name)
        w = int(self.request.get("w","0"))
        h = int(self.request.get("h","0"))
        mime = 'image/jpeg' 
        self.response.headers['Content-Type'] = mime
        self.response.out.write(resize(img.body,(w,h)))
        
class ImagePageHandler(PublicHandler):
    def get(self,key_name):
        try:
            img = get_or_404(Image.get_by_key_name,key_name)
            #cms = Comments.get_comments(key_name)
            self.template_value['img']= img
            #self.template_value['cmcount']= cms.count()
            #self.template_value['cms']= cms
            imgs = Image.get_small_img(None, None, ['album', img.album])
            self.template_value['ablum_newimg']= imgs
            self.template_value['Newimg']= Image.get_small_img(None, None, None)
            self.template_value['Hotimg']= Image.get_small_img(['hoted', 'view_count'], None, None)
            self.template_value['Likeimg']= Image.get_small_img(['ilked', 'like_count'], None, None)
            self.template_value['ablumSide']= Album.get_album_list(32)
            self.render('img.html')
        except apiproxy_errors.OverQuotaError, message:
            #Log the error.
            logging.error(message)
            self.template_value['url']='http://p1.vchen.tk/d/'+key_name+'/'
            self.render('relocation.html')
        
class ImageUploadHandler(PublicHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'application/json'
        self.response.out.write(simplejson.dumps({'result':False}))
         
    def post(self):
        skey = self.request.get("skey")
        logging.info(skey)
        if skey != self.settings.skey:
            self.response.out.write("")
        try:
            album = self.request.get("album")
            bf = self.request.get("Filedata")
            name = unicode(self.request.body_file.vars["Filedata"].filename,'utf-8')
            mime = getImageInfo(bf)[0]
            album = Album.get_by_key_name(album)
            img =Image.add(album,name,mime,bf)
            self.response.out.write(img.copyurl)
        except:
            self.response.out.write("")

class ComentsListHandler(PublicHandler):
    def get(self, key_name):
         p = self.request.get("p", 1)
         self.response.headers['Content-Type'] = 'application/json'
         self.response.out.write(Comments.get_comments(key_name, p))

                                    
class ImageDownloadHandler(PublicHandler):
    def get(self,key_name):
        img = get_or_404(Image.get_by_key_name_with_cache,key_name)
        self.response.headers['Content-Type'] = "application/octet-stream; CHARSET=utf8"
        self.response.headers['Content-Disposition']='attachment; filename=%s' % img.name.encode('utf-8')
        self.response.out.write(img.body)

class GetVerificationCodeHandler(PublicHandler):
    def get(self):
        img = getVerificationCode(VERIFICODELEN)
        logging.info(len(img))
        nowt = time.ctime()
        self.response.headers['Content-Type'] = 'image/png'
        self.response.headers['Date'] = nowt
        self.response.headers['ETag']= "%s:30:verification_code.png" % (VERIFICODELEN*30)
        self.response.headers['Cache-Control']= "max-age=315360000"
        self.response.headers['Last-Modified']= nowt
        self.response.out.write(img)
        
class LogoutHandler(PublicHandler):
    def get(self):
        user = users.get_current_user()
        if user:
            return self.redirect(users.create_logout_url("/"))
            
class UpdateLikeHandler(PublicHandler):
    def get(self,key_name):
        if key_name is not None:
            session_id = read_cookies('FCD_SESSION_ID')
            self.response.out.write(Image.updateLike(key_name, session_id))
        else:
            self.response.out.write('E_KEY_NONE')

class LoginHandler(PublicHandler):
    def get(self):
        user = users.get_current_user()
        if user and users.is_current_user_admin() :
            return self.redirect("/a/upload/")
        return self.redirect(users.create_login_url("/a/upload/"))
    
class FeedIndexHandler(FeedHandler):
    def get(self):
        imgs = Image.all().order('-created').fetch(10)
        self.template_value['imgs']=imgs
        self.template_value['lastupdated'] = imgs[0].created if len(imgs) >0 else datetime.datetime.now()
        self.response.headers['Content-Type'] = "application/atom+xml"
        self.response.out.write(self.get_render("rss.xml"))
    
class FeedAlbumHandler(FeedHandler):
    def get(self,key_name):
        album = get_or_404(Album.get_by_key_name,key_name)
        imgs = Image.all().filter('album =',album).order('-created').fetch(10)
        self.template_value['imgs']=imgs
        self.template_value['lastupdated'] = imgs[0].created if len(imgs) >0 else datetime.datetime.now()
        self.response.headers['Content-Type'] = "application/atom+xml"
        self.response.out.write(self.get_render("rss.xml"))
        
class IEHandler(FeedHandler):
    def get(self):
        self.response.out.write(self.get_render("ie.html"))
        
        
def main():
        application = webapp.WSGIApplication ([
                                            ('/', IndexHandler),
                                           ('/b/(?P<key_name>[a-z0-9]+)/?',AlbumListHandler), 
                                           ('/(?P<size>[f|s])/(?P<key_name>[a-z0-9]+)/?',ImageViewHandler),
                                           ('/d/(?P<key_name>[a-z0-9]+)/?',ImagePageHandler),
                                           #('/t/(?P<key_name>[a-z0-9]+)/?',ImageResizeTestHandler),
                                           ('/e/(?P<key_name>[a-z0-9]+)/?',ImageDownloadHandler),
                                           ('/u/',ImageUploadHandler),
                                           ('/logout/',LogoutHandler),
                                           ('/login/',LoginHandler),
                                           ('/ie/',IEHandler),
                                           ('/il/(?P<key_name>[a-z0-9A-Z_]+)/?',ImageListHandler),
                                           ('/ac/',AddComentsHandler),
                                           ('/cl/(?P<key_name>[a-z0-9]+)/?',ComentsListHandler),
                                           ('/ul/(?P<key_name>[a-z0-9]+)/?',UpdateLikeHandler),
                                           ('/vc/',GetVerificationCodeHandler),
                                           
                                           #Feed
                                           (r'/feed/?',FeedIndexHandler),
                                           (r'/feed/(?P<key_name>[a-z0-9]+)/?',FeedAlbumHandler),
                                            ],
                                             debug=settings.DEBUG)
        util.run_wsgi_app(application)

if __name__=='__main__':
    main()
